Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose field formatters in kibana server #12625

Merged
merged 15 commits into from
Jul 7, 2017
Merged

Conversation

nreese
Copy link
Contributor

@nreese nreese commented Jun 30, 2017

Move field formatters from ui/public to common so they can be used in both client and server.

Field formatters are exposed on the server via decorating the server with fieldFormatters which is an instance of FieldFormatsService . FieldFormatsService closely parallels how field formatters are exposed on the client by proving methods like getDefaultInstance and getType.

The FieldFormat classes were also updated. Previously, the FieldFormats exported a function. Executing the function returned the FieldFormat class. Now the FieldFormats directly export a Class.

Copy link
Contributor

@kobelb kobelb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The additional tests are great!! Just a few comments/questions.


let fieldFormats;
beforeEach(function () {
fieldFormats = new FieldFormatsService;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add some parens here so it's new FieldFormatsService()


const config = {};
config['format:defaultTypeMap'] = {
'ip': { 'id': 'ip', 'params': {} },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The items besides number aren't used by this test, can we remove them?

@@ -1,6 +1,6 @@
import _ from 'lodash';
import numeral from 'numeral';
import { FieldFormat } from 'ui/index_patterns/_field_format/field_format';
import numeral from '@spalger/numeral';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider moving this to elastic/numeral now that https://github.com/elastic/numeral-js exists?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created @elastic/numeral-js and upgraded to numeral 3.0 at the same time, pretty sure we'll have to publish the old version at @spalger/numeral-js in the new package if we want to move it over. That said, I'm not opposed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this wait for a separate PR? This seems like an existing artifact that is outside the scope of this PR and I am trying to get this PR finished ASAP since another feature is dependent on it and Tuesday is feature cutoff.

import { getUiSettingDefaults } from '../core_plugins/kibana/ui_setting_defaults';

export function fieldFormatsMixin(kbnServer, server) {
server.decorate('server', 'uiSettingDefaults', getUiSettingDefaults());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't feel like it belongs here, specifically because it's related to uiSettings. I know you're using the uiSettingDefaults with the fieldFormats, but the fieldFormatsMixin really shouldn't be responsible for this.

Additionally, you should be able to do uiSettings.getDefaults(); and not have to expose this separately.

Copy link
Contributor Author

@nreese nreese Jul 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uiSettings.getDefaults() is just a wrapper around options.getDefaults. If options.getDefaults is not provided than the default implementation of '() => ({})' is used. I was unable to figure out how to create a functioning getDefaults implementation to pass to server.uiSettingsServiceFactory that would return the defaults. Please advise on how to implement getDefaults that properly returns the results of getUiSettingDefaults().

If field_formats_mixin is not the place, then where should uiSettingDefaults be exposed to the server?

Copy link
Contributor Author

@nreese nreese Jul 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind. Spencer straightened my out and you are correct. After a rebase, getDefaults is populated and spitting out the correct values. I will remove the uiSettingsDefaults decorator.

@@ -1,6 +1,6 @@
import { AggTypesBucketsBucketAggTypeProvider } from 'ui/agg_types/buckets/_bucket_agg_type';
import { AggTypesBucketsCreateFilterRangeProvider } from 'ui/agg_types/buckets/create_filter/range';
import { FieldFormat } from 'ui/index_patterns/_field_format/field_format';
import { FieldFormat } from '../../../../core_plugins/kibana/common/field_formats/field_format';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be reaching inside the core_plugins/kibana folder from within src/ui/public? What made you and @spalger choose to put the common folder inside the kibana plugin and not a direct descendant of src/? This same issue applies to a few other situations below as well.

@@ -0,0 +1,29 @@
import { asPrettyString } from '../../utils/as_pretty_string';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were any changes made to the types that are showing up as additions and not renames in the diff?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The types changed a lot. Instead of being wrapped in a function, now they just export the FieldFormat class

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, I'll give them a closer look then :)

];
}

ColorFormat.prototype._convert = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ColorFormat.prototype._convert should be able to just me moved to a `_convert_method on the ColorFormat class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to move those under the class with PR - Remove lodash mixin dependencies from Field Formatters but things are messy because _convert is an object and not a function and the way _convert is used in content types make references to this tricky. @stacey-gammon and I decided it was best to leave this alone for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah... interesting... I'm fine leaving it as is for now in that case.

static outputFormats = outputFormats;
}

DurationFormat.prototype.getParamDefaults = function () {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to a regular method on the DurationFormat class instead of modifying the prototype as well?

static fieldType = '_source';
}

SourceFormat.prototype._convert = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment about not extending the prototype directly.

];
}

UrlFormat.prototype._convert = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Copy link
Contributor

@spalger spalger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still working complete testing, but some early feedback

@@ -0,0 +1,45 @@
export class FieldFormatsService {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, this belongs in src/ui/field_formats/field_formats_service.js, not the kibana plugin. It's not optional like the kibana plugin theoretically is.

describe('Duration Format', function () {

test({ inputFormat: 'seconds', outputFormat: 'humanize' })
(-60, 'minus a minute')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting style, but I'm thinking this would be a little less mind bending as:

defineTests({
  inputFormat: 'seconds',
  outputFormat: 'humanize',
  fixtures: [
    [ 60, 'a minute' ],
    // or 
    { input: -60, output: 'minus a minute' },
  ]
})

@@ -0,0 +1,45 @@
export class FieldFormatsService {
constructor() {
this.fieldFormats = new Map();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell this is intended for internal use only, it should be prefixed with an _.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't actually a rule in our style guide, right? Airbnb also says not to use the leading underscore (https://github.com/airbnb/javascript#naming--leading-underscore), though we never officially committed to airbnb style guide asfaik.

Maybe we need a "vote" issue for this so we can put something in our style guide, because I see inconsistent use of leading underscores.

import { FieldFormatsService } from '../core_plugins/kibana/common/field_formats/field_formats';

export function fieldFormatsMixin(kbnServer, server) {
server.decorate('server', 'fieldFormats', new FieldFormatsService());
Copy link
Contributor

@spalger spalger Jul 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could improve the ergonomics here a bit:

  1. How about making more instances of the FieldFormatService that are configured with a getConfig() function, rather than having a singleton that taked getConfig as an argument?

  2. If this followed the pattern UiSettings uses, and also depended on UiSettings formally, it could look like this:

    // for use in the context of a request, the default context
    server.decorate('request', 'getFieldFormatService', async function () {
      return await server.fieldFormatServiceFactory(this.getUiSettingsService())
    })
    
    // for use outside of the request context, for special cases
    server.decorate('server', 'fieldFormatServiceFactory', async function (uiSettingsService) {
      const configVals = await ...;
      const getConfig = (key) => configVals[key];
      return new FieldFormatService({ getConfig });
    });

Copy link
Contributor

@kobelb kobelb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@spalger spalger added review Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc labels Jul 7, 2017
@nreese nreese merged commit 363a065 into elastic:master Jul 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
review Team:Core Core services & architecture: plugins, logging, config, saved objects, http, ES client, i18n, etc v6.0.0-beta1 v6.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants